package com.tudouji.project.pay.service.impl;

import com.tudouji.common.utils.DateUtils;
import com.tudouji.common.utils.IdUtils;
import com.tudouji.common.utils.SecurityUtils;
import com.tudouji.framework.web.domain.AjaxResult;
import com.tudouji.project.bill.domain.Recharge;
import com.tudouji.project.bill.domain.Sellform;
import com.tudouji.project.bill.mapper.SellformMapper;
import com.tudouji.project.bill.service.ISellformService;
import com.tudouji.project.bill.service.impl.SellformServiceImpl;
import com.tudouji.project.customer.domain.Cashflow;
import com.tudouji.project.customer.domain.Customer;
import com.tudouji.project.customer.mapper.CashflowMapper;
import com.tudouji.project.customer.mapper.CustomerMapper;
import com.tudouji.project.customer.service.IReceivableflowService;
import com.tudouji.project.customer.service.impl.CashflowServiceImpl;
import com.tudouji.project.customer.service.impl.CustomerServiceImpl;
import com.tudouji.project.pay.domain.SfPrebalanceRecord;
import com.tudouji.project.pay.mapper.SfPrebalanceRecordMapper;
import com.tudouji.project.pay.service.ISfPrebalanceRecordService;
import com.tudouji.project.system.domain.SysUser;
import com.tudouji.project.system.service.ISysUserService;
import com.tudouji.project.system.service.impl.BusinesscodeServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * 销售订单回款核销记录Service业务层处理
 *
 * @author tudouji
 * @date 2022-09-22
 */
@Service
@Slf4j
public class SfPrebalanceRecordServiceImpl implements ISfPrebalanceRecordService {
    @Autowired
    private SfPrebalanceRecordMapper sfPrebalanceRecordMapper;
    @Autowired
    private ISfPrebalanceRecordService prebalanceRecordService;
    @Autowired
    private CustomerMapper customerMapper;
    @Autowired
    private SellformMapper sellformMapper;
    @Autowired
    private BusinesscodeServiceImpl codeService;
    @Autowired
    private CashflowMapper cashflowMapper;
    @Autowired
    private IReceivableflowService receivableflowService;
    @Autowired
    private SellformServiceImpl sellformService;

    @Autowired
    private CustomerServiceImpl customerService;
    @Autowired
    private ISysUserService sysUserService;

    /**
     * 查询销售订单回款核销记录
     *
     * @param id 销售订单回款核销记录ID
     * @return 销售订单回款核销记录
     */
    @Override
    public SfPrebalanceRecord selectSfPrebalanceRecordById(Long id) {
        return sfPrebalanceRecordMapper.selectSfPrebalanceRecordById(id);
    }

    @Override
    public SfPrebalanceRecord selectSfPrebalanceRecordBySellformId(Long id) {
        return sfPrebalanceRecordMapper.selectSfPrebalanceRecordBySellformId(id);
    }

    /**
     * 查询销售订单回款核销记录列表
     *
     * @param sfPrebalanceRecord 销售订单回款核销记录
     * @return 销售订单回款核销记录
     */
    @Override
    public List<SfPrebalanceRecord> selectSfPrebalanceRecordList(SfPrebalanceRecord sfPrebalanceRecord) {
        return sfPrebalanceRecordMapper.selectSfPrebalanceRecordList(sfPrebalanceRecord);
    }

    @Override
    public List<SfPrebalanceRecord> selectSfPrebalanceRecordListreverseIdisNull(SfPrebalanceRecord sfPrebalanceRecord) {
        return sfPrebalanceRecordMapper.selectSfPrebalanceRecordListreverseIdisNull(sfPrebalanceRecord);
    }

    /**
     * 新增销售订单回款核销记录
     *
     * @param sfPrebalanceRecord 销售订单回款核销记录
     * @return 结果
     */
    @Override
    public int insertSfPrebalanceRecord(SfPrebalanceRecord sfPrebalanceRecord) {
        sfPrebalanceRecord.setCreateTime(DateUtils.getNowDate());
        return sfPrebalanceRecordMapper.insertSfPrebalanceRecord(sfPrebalanceRecord);
    }

    /**
     * 修改销售订单回款核销记录
     *
     * @param sfPrebalanceRecord 销售订单回款核销记录
     * @return 结果
     */
    @Override
    public int updateSfPrebalanceRecord(SfPrebalanceRecord sfPrebalanceRecord) {
        sfPrebalanceRecord.setUpdateTime(DateUtils.getNowDate());
        return sfPrebalanceRecordMapper.updateSfPrebalanceRecord(sfPrebalanceRecord);
    }

    /**
     * 批量删除销售订单回款核销记录
     *
     * @param ids 需要删除的销售订单回款核销记录ID
     * @return 结果
     */
    @Override
    public int deleteSfPrebalanceRecordByIds(Long[] ids) {
        return sfPrebalanceRecordMapper.deleteSfPrebalanceRecordByIds(ids);
    }

    /**
     * 删除销售订单回款核销记录信息
     *
     * @param id 销售订单回款核销记录ID
     * @return 结果
     */
    @Override
    public int deleteSfPrebalanceRecordById(Long id) {
        return sfPrebalanceRecordMapper.deleteSfPrebalanceRecordById(id);
    }

    /**
     * 核销
     *
     * @param record 本次生成的核销数据
     */
    @Override
    @Transactional
    public void hexiao(SfPrebalanceRecord record) {
        Customer customer = customerMapper.selectCustomerById(record.getCustomerguid());


        //首先检查核销队列中当前销售订单是否还存在其他状态为 “已核销”的核销数据，则系统自动完成该笔核销数据的“反核销”：反向操作（累加预收款）即可。
        SfPrebalanceRecord prebalanceRecord = sfPrebalanceRecordMapper.selectSfPrebalanceRecordBySellformId(record.getSellformId());
        Sellform sellform = sellformMapper.selectSellformById(record.getSellformId());

        //20231017 全额预付的正常核销，上车付款、或者货到付款的，检查日期
        if(!sellformService.availableRecbalance(sellform,3)){
            return;
        }

        if (null != prebalanceRecord) {
            prebalanceRecord.setStatus(3);
            prebalanceRecord.setReverseId(record.getId());
            prebalanceRecord.setUpdateTime(DateUtils.getNowDate());
            sfPrebalanceRecordMapper.updateSfPrebalanceRecord(prebalanceRecord);

            insertCashFlowZ(prebalanceRecord, customer, sellform);

            customer.setPrebalance(customer.getPrebalance().add(prebalanceRecord.getAmount()));
            customer.setCurrprebalance(customer.getCurrprebalance().add(prebalanceRecord.getAmount()));
            customerMapper.updateCustomer(customer);

            record.setReverseId(prebalanceRecord.getId());
        }

        //如果余额足够核销，则核销该销售订单
        //20231009 以前的自动核销逻辑为：不管客户预收款余额是否足够，直接核销，余额不够的体现为负数
        //20231009 由于需要统计预期订单、因此需要明确的订单回款日期，所以，余额不足的不再核销
        if (customer.getPrebalance().compareTo(record.getAmount()) == 1 || customer.getPrebalance().compareTo(record.getAmount()) == 0) {

            insertCashFlowF(record, customer, sellform);


            //20231010 处理针对该笔订单的应收款 ， 暂不处理全款预付订单
            if(sellform.getPaytype().intValue() != 1 &&
                    sellformService.availableRecbalance(sellform,2)){
                receivableflowService.saveRecableLogs(customer,sellform,record.getAmount(),2,"sellform",sellform.getId(),sellform.getSellcode(),"回款核销");
            }

            customer.setPrebalance(customer.getPrebalance().subtract(record.getAmount()));
            customer.setCurrprebalance((customer.getCurrprebalance() == null ? BigDecimal.ZERO : customer.getCurrprebalance()).subtract(record.getAmount()));
            customerMapper.updateCustomer(customer);

            sellform.setMoneybackStatus(3);
            sellform.setBackmoneytime(DateUtils.getNowDate());
            //2023.10.12计算实际回款天数，以及是否预期标识
            if (sellform.getPaytype() == 3){
                sellform.setActualPaymentDays(Integer.valueOf(DateUtils.getDateDiff(sellform.getBackmoneytime(), sellform.getLoadDate()) +""));
                if (sellform.getActualPaymentDays() - sellform.getSettlebilling() > 0){
                    sellform.setOverdueFlag(1);
                }
            }
            sellformMapper.updateSellform(sellform);

            record.setStatus(100);
            record.setUpdateTime(DateUtils.getNowDate());
            sfPrebalanceRecordMapper.updateSfPrebalanceRecord(record);


        } else {
            sellform.setMoneybackStatus(2);
            sellformMapper.updateSellform(sellform);
            record.setStatus(2);
            record.setUpdateTime(DateUtils.getNowDate());
            sfPrebalanceRecordMapper.updateSfPrebalanceRecord(record);
        }
    }

    @Override
    @Transactional
    public void hexiaoRecbalanceManual(){
        log.debug("====hexiaoRecbalanceManual start === ");
        //遍历客户信息
        Customer lookup=new Customer();
        List<Customer> customers = customerMapper.selectCustomerList(lookup);
        SysUser user = sysUserService.selectUserById(1l);
        String remark=null;
        int manualCount=0;
        for(Customer customer:customers){
            if (customer.getRecbalanceManual() != null
                    && customer.getRecbalanceManual().compareTo(BigDecimal.ZERO) == 1
                    && customer.getPrebalance()!=null
                    && customer.getPrebalance().compareTo(BigDecimal.ZERO) == 1){
                manualCount++;
                //当前客户有初始化应收账款，且，预收款余额大于0，则可以核销
                BigDecimal amount = customer.getPrebalance().compareTo(customer.getRecbalanceManual()) == 1
                         ? customer.getRecbalanceManual():customer.getPrebalance();

                amount=amount.negate();
                BigDecimal recBalance = customer.getRecbalanceManual().add(amount);
                remark = "核销初始应收款";
                Recharge recharge = new Recharge();
                recharge.setCode("HxInit");
                recharge.setType(3);
                recharge.setAmount(amount);
                customerService.recharge(customer,amount,user,recharge,3,remark);

                customer.setRecbalanceManual(recBalance);

                //同时需要核销掉应收款余额
                //伪装sellform调用saveRecableLogs,amount已经设置成负数了，但是saveRecableLogs
                //方法中会根据type进行设置，所以，再变为正数调用saveRecableLogs
                Sellform sellform = new Sellform();
                sellform.setCreateBy(1l);
                sellform.setFinalamount(amount.negate());
                receivableflowService.saveRecableLogs(customer,sellform,amount.negate(),2,"notable",-1l,"HxInit","核销初始应收账款");
                customerService.updateCustomer(customer);
            }
        }
        log.debug("====hexiaoRecbalanceManual end === "+manualCount + " customers processed");
    }
    /**
     * 加钱
     *
     * @param record
     * @param customer
     * @param sellform
     */
    private void insertCashFlowZ(SfPrebalanceRecord record, Customer customer, Sellform sellform) {
        //账户余额流水更新
        Cashflow cashflow = new Cashflow();
        cashflow.setCustomerid(customer.getGuid());
        cashflow.setLinkid(record.getId() + "");
        cashflow.setLinkedTable("sf_prebalance_record");
        cashflow.setOperatorid(sellform.getOperatorid());
        cashflow.setOperator(sellform.getApplyname());
        cashflow.setAmount(record.getAmount());
        cashflow.setPrebalance(customer.getPrebalance().add(record.getAmount()));
        cashflow.setType(1);
        cashflow.setCreatetime(new Date());
        cashflow.setCode(sellform.getSellcode());
        cashflow.setGuid(IdUtils.fastSimpleUUID());
        cashflowMapper.insertCashflow(cashflow);
    }

    /**
     * 减钱
     *
     * @param record
     * @param customer
     * @param sellform
     */
    private void insertCashFlowF(SfPrebalanceRecord record, Customer customer, Sellform sellform) {
        //账户余额流水更新
        Cashflow cashflow = new Cashflow();
        cashflow.setCustomerid(customer.getGuid());
        cashflow.setLinkid(record.getId() + "");
        cashflow.setLinkedTable("sf_prebalance_record");
        cashflow.setOperatorid(sellform.getOperatorid());
        cashflow.setOperator(sellform.getApplyname());
        cashflow.setAmount(record.getAmount().negate());
        cashflow.setPrebalance(customer.getPrebalance().subtract(record.getAmount()));
        cashflow.setType(3);
        cashflow.setCreatetime(new Date());
        cashflow.setCode(sellform.getSellcode());
        cashflow.setGuid(IdUtils.fastSimpleUUID());
        cashflowMapper.insertCashflow(cashflow);
    }

    /**
     * 手工反核销
     *
     * @param prebalanceRecord 上次生成的核销数据
     */
    @Override
    public void hexiaofan(SfPrebalanceRecord prebalanceRecord) {
        boolean hexiaofan = true;
        Customer customer = customerMapper.selectCustomerById(prebalanceRecord.getCustomerguid());
        //状态=2、type=1的，需要删除掉该笔数据：status设置为0，并且生成一笔type=2的对应反核销记录，备查。
        if (2 == prebalanceRecord.getType()) {
            SfPrebalanceRecord endRecord2Rever = prebalanceRecord;
            endRecord2Rever.setType(2);
            endRecord2Rever.setStatus(0);
            endRecord2Rever.setReverseId(prebalanceRecord.getId());
            sfPrebalanceRecordMapper.insertSfPrebalanceRecord(endRecord2Rever);
            prebalanceRecord.setStatus(0);
            prebalanceRecord.setReverseId(endRecord2Rever.getId());
            sfPrebalanceRecordMapper.updateSfPrebalanceRecord(prebalanceRecord);
            hexiaofan = false;
        }

        if (hexiaofan) {
            SysUser sysUser = SecurityUtils.getLoginUser().getUser();
            SfPrebalanceRecord record = prebalanceRecordService.createPrebalanceRecord(prebalanceRecord.getSellformId(), prebalanceRecord.getCode(), prebalanceRecord.getAmount(), sysUser, 2);

            prebalanceRecord.setStatus(3);
            prebalanceRecord.setReverseId(record.getId());
            prebalanceRecord.setUpdateTime(DateUtils.getNowDate());
            sfPrebalanceRecordMapper.updateSfPrebalanceRecord(prebalanceRecord);

            record.setStatus(100);
            record.setUpdateTime(DateUtils.getNowDate());
            record.setReverseId(prebalanceRecord.getId());
            sfPrebalanceRecordMapper.updateSfPrebalanceRecord(record);

            Sellform sellform = sellformMapper.selectSellformById(prebalanceRecord.getSellformId());

            //账户余额流水更新
            insertCashFlowZ(prebalanceRecord, customer, sellform);

            sellform.setMoneybackStatus(1);
            sellformMapper.updateSellform(sellform);

            customer.setPrebalance(customer.getPrebalance().add(prebalanceRecord.getAmount()));
            customer.setCurrprebalance(customer.getCurrprebalance().add(prebalanceRecord.getAmount()));
            customerMapper.updateCustomer(customer);
        }
    }

    /**
     * 如果当前订单核销状态为已核销，则冲回已核销数据（将客户预收款余额冲回），并修改当前订单核销状态为未核销
     */
    @Override
    public void hexiaoReverse(SfPrebalanceRecord prebalanceRecord) {
        Customer customer = customerMapper.selectCustomerById(prebalanceRecord.getCustomerguid());
        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
        SfPrebalanceRecord record = prebalanceRecordService.createPrebalanceRecord(prebalanceRecord.getSellformId(), prebalanceRecord.getCode(), prebalanceRecord.getAmount(), sysUser, 2);

        prebalanceRecord.setStatus(3);
        prebalanceRecord.setReverseId(record.getId());
        prebalanceRecord.setUpdateTime(DateUtils.getNowDate());
        sfPrebalanceRecordMapper.updateSfPrebalanceRecord(prebalanceRecord);

        record.setStatus(100);
        record.setUpdateTime(DateUtils.getNowDate());
        record.setReverseId(prebalanceRecord.getId());
        sfPrebalanceRecordMapper.updateSfPrebalanceRecord(record);

        Sellform sellform = sellformMapper.selectSellformById(prebalanceRecord.getSellformId());

        //账户余额流水更新
        insertCashFlowZ(prebalanceRecord, customer, sellform);

        sellform.setMoneybackStatus(1);
        sellformMapper.updateSellform(sellform);

        customer.setPrebalance(customer.getPrebalance().add(prebalanceRecord.getAmount()));
        customer.setCurrprebalance(customer.getCurrprebalance().add(prebalanceRecord.getAmount()));
        customerMapper.updateCustomer(customer);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    public AjaxResult reverse(Long id) {
        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
        //核销
        SfPrebalanceRecord endRecord = sfPrebalanceRecordMapper.selectHeXiaoRecordById(id);
        if (null == endRecord) {
            return AjaxResult.error("核销记录不满足反核销条件！");
        }
        prebalanceRecordService.hexiaofan(endRecord);
        return AjaxResult.success();
    }

    /**
     * 销售订单结算确认完成后，记录该销售订单到“待核销”队列（新增待核销销售订单表）。系统自动批量定时进行自动核销。
     */
    @Override
    public SfPrebalanceRecord createPrebalanceRecord(Long id, String sellcode, BigDecimal finalamount, SysUser user, Integer type) {
        SfPrebalanceRecord prebalanceRecord = new SfPrebalanceRecord();
        prebalanceRecord.setSellformId(id);
        prebalanceRecord.setStatus(1);
        prebalanceRecord.setType(type);
        prebalanceRecord.setCode(sellcode);
        prebalanceRecord.setAmount(finalamount);
        prebalanceRecord.setCreateBy(user.getUserId());
        prebalanceRecord.setCreateTime(DateUtils.getNowDate());
        sfPrebalanceRecordMapper.insertSfPrebalanceRecord(prebalanceRecord);
        return prebalanceRecord;
    }
    public List<SfPrebalanceRecord> hdfkHeXiaoRecordForByCustGuid(String customGuid){
        return sfPrebalanceRecordMapper.hdfkHeXiaoRecordForByCustGuid(customGuid);
    }

}
